package org.hackystat.sdsa.analyzer.control.rules.tdd;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import jess.Batch;
import jess.Fact;
import jess.JessException;
import jess.QueryResult;
import jess.RU;
import jess.Rete;
import jess.Value;
import jess.ValueVector;

import org.junit.Before;
import org.junit.Test;

/**
 * Test two-way heuristic algorithm of TDD conformance evaluation.
 * 
 * @author Hongbing Kou
 *
 */
public class TestTDDConformanceHeuristicAlgorithm {
  /** Rete engine. */
  private Rete engine;

  /**
   * Sets up rete network.
   * 
   * @throws Exception If error while setting up data.
   */
  @Before public void setUp() throws Exception {
    this.engine = new Rete();
    String ruleplace = "/org/hackystat/sdsa/analyzer/control/rules/tdd/";

    Batch.batch(ruleplace + "TDDConformanceHeuristicAlgorithm.clp", this.engine);
  }
  
  /**
   * Asserts an episode's index and its classification result into rete engine.
   * 
   * @param index Index of the episode
   * @param category Episode category
   * @param subtype Category subtype.
   * @return The asserted fact.
   * @throws JessException If there is error happened.
   */
  public Fact assertConformanceEpisode(int index, String category, String subtype) 
      throws JessException  {
    Fact f = new Fact("EpisodeConformance", engine);
    f.setSlotValue("index", new Value(index, RU.INTEGER));
    f.setSlotValue("category", new Value(category, RU.STRING));
    f.setSlotValue("subtype", new Value(category, RU.STRING));
    Fact assertedFact = this.engine.assertFact(f);
    return assertedFact;
  }  
  

  /**
   * Test TDD conformance of pattern one.
   * 
   * @throws Exception If failed while testing
   */
  @Test public void testPatternOne() throws Exception {
    engine.reset();
    String truthString = "True";
    
    String tddBehavior = "test-first";
    String testAdditionBehavior = "test-addition";
    String refactoringBehavior = "refactoring";
    String behaviorSubtype = "1";
    assertConformanceEpisode(1, tddBehavior, behaviorSubtype);
    assertConformanceEpisode(2, refactoringBehavior, behaviorSubtype);
    assertConformanceEpisode(3, testAdditionBehavior, behaviorSubtype);
    assertConformanceEpisode(4, "test-last", behaviorSubtype);
    assertConformanceEpisode(5, refactoringBehavior, behaviorSubtype);
    assertConformanceEpisode(6, testAdditionBehavior, behaviorSubtype);
    assertConformanceEpisode(7, refactoringBehavior, behaviorSubtype);
    assertConformanceEpisode(8, tddBehavior, behaviorSubtype);
    assertConformanceEpisode(9, testAdditionBehavior, behaviorSubtype);
    assertConformanceEpisode(10, testAdditionBehavior, behaviorSubtype);
    engine.run();
    
    String episodeQuery = "episode-tdd-conformance-query-by-index";
    String tddConformance = "isTDD";
    QueryResult result = engine.runQueryStar(episodeQuery, 
        (new ValueVector()).add(new Value(1, RU.INTEGER)));
    assertTrue("Result to episode 1", result.next());
    assertEquals("Test episode 1", truthString, result.getString(tddConformance));
    
    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(2, RU.INTEGER)));
    assertTrue("Result to episode 2", result.next());
    assertEquals("Test episode 2", truthString, result.getString(tddConformance));
    
    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(3, RU.INTEGER)));
    assertTrue("Result to episode 3", result.next());
    assertEquals("Test episode 3", truthString, result.getString(tddConformance));
    
    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(4, RU.INTEGER)));
    assertTrue("Result to episode 4", result.next());
    assertEquals("Test episode 4", "False", result.getString(tddConformance));

    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(5, RU.INTEGER)));
    assertTrue("Result to episode 5", result.next());
    assertEquals("Test episode 5", truthString, result.getString(tddConformance));

    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(6, RU.INTEGER)));
    assertTrue("Result to episode 6", result.next());
    assertEquals("Test episode 6", truthString, result.getString(tddConformance));
    
    result = engine.runQueryStar(episodeQuery, 
        (new ValueVector()).add(new Value(7, RU.INTEGER)));
    assertTrue("Result to episode 7", result.next());
    assertEquals("Test episode 7", truthString, result.getString(tddConformance));
    
    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(8, RU.INTEGER)));
    assertTrue("Result to episode 8", result.next());
    assertEquals("Test episode 8", truthString, result.getString(tddConformance));

    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(9, RU.INTEGER)));
    assertTrue("Result to episode 9", result.next());
    assertEquals("Test episode 9", truthString, result.getString(tddConformance));

    result = engine.runQueryStar(episodeQuery, (new ValueVector()).add(new Value(10, RU.INTEGER)));
    assertTrue("Result to episode 10", result.next());
    assertEquals("Test episode 10", truthString, result.getString(tddConformance));
  }
}
